<script lang="tsx" setup>
import { computed, reactive, ref, watch } from 'vue';
import type { FormRules, TreeOption } from 'naive-ui';
import { repeat } from 'lodash-es';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import type { DictDataOption } from '@/typings/global';
import { addClient, editClient, getClient } from '@/service/api/open/client';
import FormLabelExtends from '@/components/custom/form-label-extends.vue';
import { generateClientKey, generateClientSecurity } from '@/utils/common';
import type { MenuTreeOption, RoleVO } from '@/service/types/system';
import { addRole, editRole, getRole } from '@/service/api/system/role';
import { fetchGetMenuTree, getRoleMenuTreeselect } from '@/service/api/system/menu';
type Model = Pick<RoleVO, 'status' | 'roleId' | 'roleName' | 'roleKey' | 'roleSort' | 'menuCheckStrictly' | 'menuIds'>;
interface Props {
  operateType: NaiveUI.TableOperateType;
  currentId?: string | number | null | unknown;
  sysNormalDisable: DictDataOption[];
}
const loading = ref(false);
interface Emits {
  (e: 'submitted'): void;
}
const show = ref<boolean>(false);
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
defineOptions({
  name: 'ClientForm'
});
const { formRef, validate, restoreValidation } = useNaiveForm();
const { createRequiredRule } = useFormRules();
const rules: FormRules = {
  roleKey: {
    required: true,
    message: '角色权限字符不能为空',
    trigger: 'blur'
  },
  roleName: {
    required: true,
    message: '角色名称',
    trigger: 'blur'
  },
  deviceType: createRequiredRule('设备类型不能为空'),
  roleSort: createRequiredRule('排序不能为空'),
  status: {
    required: true,
    message: '请选择状态',
    trigger: 'blur'
  }
};

const visible = defineModel<boolean>('visible', {
  default: false
});
const currentModelData = ref<RoleVO>();
const model: Model = reactive(createDefaultModel());
const selectAllRef = ref<boolean>(false);
const selectChecKeys = ref<number[]>([]);
const menus = ref<MenuTreeOption[]>([]);
const allMenuIds = ref<number[]>([]);
const treeLoading = ref<boolean>(false);

const getAllIds = (data: MenuTreeOption[]): number[] => {
  const ids: number[] = [];
  const traverse = (obj: MenuTreeOption): void => {
    ids.push(obj.id as number);
    if (obj.children) {
      // 确保 children 存在
      obj.children.forEach(child => traverse(child));
    }
  };
  data.forEach(item => traverse(item));
  return ids;
};
const getMenuTree = async () => {
  treeLoading.value = true;
  const { data, error } = await fetchGetMenuTree();
  if (!error) {
    // @ts-expect-error 忽略Request请求
    const ids = getAllIds(data?.data as MenuTreeOption[]);
    allMenuIds.value = ids;
    // @ts-expect-error 忽略Request请求
    menus.value = data?.data;
    treeLoading.value = false;
  }
};
function createDefaultModel(): Model {
  return {
    roleId: '',
    status: '0',
    roleName: '',
    roleKey: '',
    roleSort: 0,
    menuIds: [],
    menuCheckStrictly: false
  };
}
const getRoleById = async (id: number) => {
  show.value = true;
  const { error, data } = await getRole(id);
  if (!error) {
    // @ts-expect-error 忽略Request请求
    currentModelData.value = data?.data;
  }
  show.value = false;
};
const getRoleMenuTree = async () => {
  treeLoading.value = true;
  const { error, data } = await getRoleMenuTreeselect(props.currentId as number);
  treeLoading.value = false;
  if (!error) {
    // @ts-expect-error 忽略Request请求
    const menusData = data?.data?.menus;
    const ids = getAllIds(menusData as MenuTreeOption[]);
    allMenuIds.value = ids;
    menus.value = menusData;
    // @ts-expect-error 忽略Request请求
    selectChecKeys.value = data?.data?.checkedKeys;
  }
};
async function handleInitModel() {
  Object.assign(model, createDefaultModel());
  if (props.operateType === 'edit' && props.currentId) {
    await getRoleById(props.currentId as number);
    await getRoleMenuTree();
    Object.assign(model, currentModelData.value);
  } else {
    getMenuTree();
  }
}

watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    restoreValidation();
  }
});

const closeModal = () => {
  visible.value = false;
};
const submitAddRole = async (params: RoleVO) => {
  const { error, data } = await addRole(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
const submitEditRole = async (params: RoleVO) => {
  const { error, data } = await editRole(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
async function handleSubmit() {
  await validate();
  loading.value = true;
  const { ...params } = model;
  params.menuIds = selectChecKeys.value as number[];
  if (!props.currentId) {
    await submitAddRole(params as RoleVO);
  } else {
    await submitEditRole({ ...params, roleId: props.currentId } as RoleVO);
  }
}

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增角色',
    edit: '修改角色'
  };
  return titles[props.operateType];
});
// 全选
const selectAll = () => {
  if (selectAllRef.value) {
    selectChecKeys.value = [];
    selectAllRef.value = false;
  } else {
    selectChecKeys.value = allMenuIds.value;
    selectAllRef.value = true;
  }
};
const handleSelectKey = (keys: any) => {
  selectChecKeys.value = keys;
};
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-740px">
    <NSpin :show="show">
      <NForm ref="formRef" :model="model" :rules="rules">
        <NGrid x-gap="12" responsive="screen" item-responsive>
          <NGi span="24 s:24 m:12">
            <NFormItemGi span="24 s:24 m:24" label="角色名称" path="roleName">
              <NInput v-model:value="model.roleName" placeholder="请输入角色名称" />
            </NFormItemGi>
            <NFormItemGi span="24 s:24 m:24" label="权限字符" path="roleKey">
              <template #label>
                <FormLabelExtends label="权限字符" tips="控制器中定义的权限字符，如：@SaCheckRole('admin')" />
              </template>
              <NInput v-model:value="model.roleKey" placeholder="请输入权限字符" />
            </NFormItemGi>
            <NFormItemGi span="24 s:24 m:24" path="roleSort" label="角色排序">
              <NInputNumber
                v-model:value="model.roleSort"
                :min="0"
                :max="99999999"
                class="w-100%"
                clearable
                placeholder="请输入角色排序"
              />
            </NFormItemGi>
            <NFormItemGi span="24 s:24 m:24" label="状态" path="status">
              <NRadioGroup v-model:value="model.status">
                <NRadioButton v-for="(item, index) in props.sysNormalDisable" :key="index" :value="item.value">
                  {{ item?.label }}
                </NRadioButton>
              </NRadioGroup>
            </NFormItemGi>
          </NGi>
          <NGi span="24 s:24 m:12" class="flex flex-col flex-gap-5px">
            <div class="flex justify-between">
              <div>菜单权限</div>
              <div class="flex flex-gap-5px">
                <NButton size="tiny">展开/折叠</NButton>
                <NButton size="tiny" @click="selectAll">全选</NButton>
              </div>
            </div>
            <div class="flex items-center justify-between pl-8px pr-5px">
              <div class="flex items-center flex-gap-8px">
                <SvgIcon class="font-size-12px" icon="nimbus:arrows-horizontal" />
                <div>父子联动</div>
              </div>
              <NCheckbox v-model:checked="model.menuCheckStrictly" />
            </div>
            <div>
              <NSpin :show="treeLoading">
                <NScrollbar class="h-300px">
                  <NTree
                    block-line
                    :cascade="model.menuCheckStrictly"
                    checkable
                    :selectable="false"
                    checkbox-placement="right"
                    block-node
                    children-field="children"
                    key-field="id"
                    :data="menus"
                    :checked-keys="selectChecKeys"
                    @update:checked-keys="handleSelectKey"
                  >
                    <template #empty>
                      <Empty />
                    </template>
                  </NTree>
                </NScrollbar>
                <!--
    :default-selected-keys="defaultCheckedKeys"
                  :checked-keys="defaultCheckedKeys"
-->
              </NSpin>
            </div>
          </NGi>

          <!--
 <NFormItemGi span="24 s:12 m:12" label="token固定超时" path="timeout">
            <template #label>
              <FormLabelExtends label="Token固定超时" tips="指定时间必定过期（单位：秒），默认七天（604800秒）" />
            </template>
            <NInputNumber
              v-model:value="model.timeout"
              :min="0"
              :max="99999999"
              class="w-100%"
              clearable
              placeholder="请输入token固定超时"
            />
          </NFormItemGi>
-->
        </NGrid>
      </NForm>
    </NSpin>

    <template #footer>
      <NSpace justify="end">
        <NButton @click="closeModal">取消</NButton>
        <NButton type="primary" :loading="loading" @click="handleSubmit">提交</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style lang="scss" scoped></style>
